Package org.python.pydev.editor.actions

Source Code of org.python.pydev.editor.actions.PyRemoveBlockComment

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* @author: ptoofani
* Created: June 2004
*/

package org.python.pydev.editor.actions;

import java.util.HashSet;
import java.util.List;

import org.eclipse.jface.action.IAction;
import org.python.pydev.core.IIndentPrefs;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editor.autoedit.DefaultIndentPrefs;

import com.aptana.shared_core.string.FastStringBuffer;
import com.aptana.shared_core.structure.Tuple;

/**
* Removes a comment block. Comment blocks are slightly different than regular
* comments created in that they provide a distinguishing element at the
* beginning and end as a separator. In this case, it is a string of
* <code>=======</code> symbols to strongly differentiate this comment block.
*
* This will handle regular comment blocks as well by removing the # token at
* the head of each line, but will also remove the block separators if they are
* present.
*
* Changes in 1.2.7: if any line of a block comment is selected, all 'adjacent' lines
* will have its comment removed (without the need to select the whole lines
*
* @author Parhaum Toofanian
* @author Fabio Zadrozny
*/
public class PyRemoveBlockComment extends PyAddBlockComment {

    /**
     * Grabs the selection information and performs the action.
     */
    public void run(IAction action) {
        try {
            if (!canModifyEditor()) {
                return;
            }

            // Select from text editor
            PySelection ps = new PySelection(getTextEditor());

            // Put cursor at the first area of the selection
            getTextEditor().selectAndReveal(perform(ps), 0);
        } catch (Exception e) {
            beep(e);
        }
    }

    /**
     * Performs the action with a given PySelection
     *
     * @param ps Given PySelection
     * @return boolean The success or failure of the action
     */
    public int perform(PySelection ps) {
        // What we'll be replacing the selected text with
        FastStringBuffer strbuf = new FastStringBuffer();

        try {
            //discover 1st line that starts the block comment
            int i;
            int startLineIndex = getStartIndex(ps);
            int endLineIndex = getEndIndex(ps);
            if (startLineIndex == -1 || endLineIndex == -1) {
                if (startLineIndex == -1 && endLineIndex == -1) {
                    return -1;
                } else if (startLineIndex == -1) {
                    startLineIndex = endLineIndex;
                } else {
                    endLineIndex = startLineIndex;
                }
            }

            // For each line, uncomment it
            for (i = startLineIndex; i <= endLineIndex; i++) {
                boolean addDelim = true;
                String spacesBefore = "";
                String line = ps.getLine(i);
                int lineLen = line.length();
                for (int j = 0; j < lineLen; j++) {
                    char c = line.charAt(j);
                    if (c == '#') {
                        //ok, it starts with # (so, remove the whitespaces before it)
                        if (j > 0) {
                            spacesBefore = line.substring(0, j);
                        }
                        line = line.substring(j);
                        break;
                    } else {
                        if (!Character.isWhitespace(c)) {
                            break;
                        }
                    }
                }
                if (line.startsWith("#")) {
                    line = line.substring(1);
                }

                //get the chars used in block-comments
                AbstractBlockCommentAction[] acts = new AbstractBlockCommentAction[] { new PyAddSingleBlockComment(),
                        new PyAddBlockComment() };
                HashSet<Character> chars = new HashSet<Character>();
                for (int j = 0; j < acts.length; j++) {
                    AbstractBlockCommentAction action = acts[j];
                    chars.add(action.getColsAndChar().o2);
                }

                if (line.length() > 0) {
                    boolean removedChar = false;
                    char lastChar = '\0';
                    for (int j = 0; j < line.length(); j++) {
                        lastChar = line.charAt(j);
                        if (!chars.contains(lastChar)) {
                            break;
                        } else {
                            removedChar = true;
                            line = line.substring(1);
                            j--;
                        }
                    }
                    if (line.length() == 0 && removedChar) {
                        addDelim = false;
                    }
                    if (removedChar && lastChar == ' ') {
                        line = line.substring(1);
                    }
                }

                if (addDelim) {
                    strbuf.append(spacesBefore);
                    strbuf.append(line);
                    String lineDelimiter = ps.getDoc().getLineDelimiter(i);
                    if (lineDelimiter != null) {
                        strbuf.append(lineDelimiter);
                    }
                }
            }

            //Ok, at this point things should be correct, but make sure than on uncomment,
            //the code goes to a proper indent position (remove spaces we may have added when creating a block).
            String string = strbuf.toString();
            List<String> lines = StringUtils.splitInLines(string);
            Tuple<Integer, String> posAndLine = new Tuple<Integer, String>(-1, "");
            for (String line : lines) {
                int firstCharPosition = PySelection.getFirstCharPosition(line);
                if (firstCharPosition < posAndLine.o1 || posAndLine.o1 < 0) {
                    posAndLine.o1 = firstCharPosition;
                    posAndLine.o2 = line;
                }
            }
            if (posAndLine.o1 > 0) {
                final String sub = posAndLine.o2.substring(0, posAndLine.o1);
                if (sub.endsWith(" ")) { //If it ends with a tab, we won't change anything (only spaces are removed -- which we may have introduced)
                    boolean allEqual = true;
                    for (String line : lines) {
                        if (!line.startsWith(sub)) {
                            allEqual = false;
                            break;
                        }
                    }
                    if (allEqual) {
                        if (sub.startsWith("\t")) {
                            //Tabs based indent: remove any ending spaces (and at this point we know a string ends with a space)
                            int j;
                            for (j = sub.length() - 1; j >= 0; j--) {
                                char c = sub.charAt(j);
                                if (c != ' ') {
                                    j++;
                                    break;
                                }
                            }
                            String newSub = sub.substring(0, j);
                            strbuf.clear();
                            for (String line : lines) {
                                strbuf.append(newSub);
                                strbuf.append(line.substring(sub.length()));
                            }

                        } else {
                            IIndentPrefs indentPrefs;
                            if (targetEditor instanceof PyEdit) {
                                PyEdit pyEdit = (PyEdit) targetEditor;
                                indentPrefs = pyEdit.getIndentPrefs();
                            } else {
                                indentPrefs = DefaultIndentPrefs.get();
                            }

                            String indentationString = indentPrefs.getIndentationString();

                            int subLen = sub.length();
                            int indentLen = indentationString.length();
                            int mod = subLen % indentLen;
                            if (mod != 0) {
                                String substring = sub.substring(subLen - mod, subLen);
                                boolean onlyWhitespaces = true;
                                for (int k = 0; k < substring.length(); k++) {
                                    if (substring.charAt(k) != ' ') {
                                        onlyWhitespaces = false;
                                        break;
                                    }
                                }
                                if (onlyWhitespaces) {
                                    String newSub = sub.substring(0, subLen - mod);
                                    strbuf.clear();
                                    for (String line : lines) {
                                        strbuf.append(newSub);
                                        strbuf.append(line.substring(sub.length()));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Replace the text with the modified information
            int startLineOffset = ps.getLineOffset(startLineIndex);
            int endLineOffset = ps.getEndLineOffset(endLineIndex);
            String endLineDelimiter = ps.getDoc().getLineDelimiter(endLineIndex);
            if (endLineDelimiter != null) {
                endLineOffset += endLineDelimiter.length();
            }
            String str = strbuf.toString();
            ps.getDoc().replace(startLineOffset, endLineOffset - startLineOffset, str);
            return startLineOffset + str.length();
        } catch (Exception e) {
            beep(e);
        }

        // In event of problems, return false
        return -1;
    }

    private int getEndIndex(PySelection ps) {
        int endLineIndex = -1;
        int i = ps.getEndLineIndex();
        while (true) {
            String line = ps.getLine(i);
            if (PySelection.isCommentLine(line)) {
                endLineIndex = i;
            } else {
                break;
            }
            i++;
        }
        return endLineIndex;
    }

    private int getStartIndex(PySelection ps) {
        int startLineIndex = -1;
        int i = ps.getStartLineIndex();
        while (true) {
            String line = ps.getLine(i);
            if (PySelection.isCommentLine(line)) {
                startLineIndex = i;
            } else {
                break;
            }
            i--;
        }
        return startLineIndex;
    }

}
TOP

Related Classes of org.python.pydev.editor.actions.PyRemoveBlockComment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.